﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;

namespace System.Data
{
    /// <summary>
    /// Provides DataFieldCollection functionality
    /// </summary>
    public class DataFieldCollection : Collection<DataField>
    {
        #region Events
        /// <summary>
        /// Is raised before data was changed
        /// </summary>
        internal event EventHandler<DataSetEventArgs> FieldValueChanging;

        /// <summary>
        /// INotifyPropertyChanged interface implementation
        /// </summary>
        internal event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        internal DataFieldCollection()
        {
        }
        #endregion

        #region Indexers
        /// <summary>
        /// Gets DataField with specified name
        /// </summary>
        /// <param name="name">DataField name</param>
        /// <returns>DataField if found, otherwise null</returns>
        public DataField this[string name]
        {
            get
            {
                // Validate argument
                if (string.IsNullOrEmpty(name))
                {
                    throw new ArgumentNullException("name");
                }

                // Do case insensitive search
                string caseInsensitiveName = name.ToUpper(CultureInfo.InvariantCulture);
                foreach (DataField dataField in this)
                {
                    if (dataField.ColumnName.ToUpper(CultureInfo.InvariantCulture).Equals(caseInsensitiveName))
                    {
                        return dataField;
                    }
                }

                return null;
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Adds field to collection
        /// </summary>
        /// <param name="dataField">Field for adding</param>
        /// <returns>Added field</returns>
        internal new DataField Add(DataField dataField)
        {
            // Validate argument
            if (dataField == null)
            {
                throw new ArgumentNullException("dataField");
            }

            dataField.PropertyChanged += new PropertyChangedEventHandler(DataField_PropertyChanged);
            dataField.FieldValueChanging += new EventHandler<DataSetEventArgs>(DataField_FieldValueChanging);
            base.Add(dataField);
            return dataField;
        }

        /// <summary>
        /// Clears DataFieldCollection
        /// </summary>
        internal new void Clear()
        {
        }

        /// <summary>
        /// Prepares DataField for removing from DatFieldCollection
        /// </summary>
        /// <param name="dataField">DataField instance</param>
        private void PrepareForRemoving(DataField dataField)
        {
            dataField.PropertyChanged -= DataField_PropertyChanged;
            dataField.FieldValueChanging -= DataField_FieldValueChanging;
        }

        /// <summary>
        /// Hides base class method
        /// </summary>
        /// <param name="dataField"></param>
        private new void Remove(DataField dataField)
        {
        }

        /// <summary>
        /// Removes DataField from DataFieldCollection
        /// </summary>
        /// <param name="fieldName">DataField name</param>
        internal void Remove(string fieldName)
        {
            DataField dataField = this[fieldName];
            this.PrepareForRemoving(dataField);
            base.Remove(dataField);
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Handles DataField.FieldValueChanging event
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Event arguments</param>
        private void DataField_FieldValueChanging(object sender, DataSetEventArgs e)
        {
            if (FieldValueChanging != null)
            {
                FieldValueChanging(sender, e);
            }
        }

        /// <summary>
        /// Handles DataField.PropertyChanged event
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Event arguments</param>
        void DataField_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(sender, e);
            }
        }
        #endregion
    }
}
